package com.fanqj.resilience4j.controller;

import com.fanqj.resilience4j.service.ITestService;
import io.github.resilience4j.bulkhead.*;
import io.vavr.control.Try;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import javax.annotation.processing.Completion;
import java.time.Duration;
import java.time.temporal.TemporalUnit;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * 隔离
 * @author <a href="mailto:fanqijin@wxchina.com">fanqj</a>
 * @Date 2021年01月26日 16:02
 * @Version 6.4.1
 */
@RestController
@RequestMapping("/bulkhead")
public class BulkheadController {

    private Bulkhead bulkhead;

    @Autowired
    private ITestService iTestService;

    @PostConstruct
    private void init() {
        BulkheadConfig defaultConfig = BulkheadConfig.custom()
                //隔离允许线程并发执行的最大数量,默认25
                .maxConcurrentCalls(2)
                //当达到并发调用数量时，新的线程执行时将被阻塞，这个属性表示最长的等待时间。默认0
                .maxWaitDuration(Duration.ZERO)
                //公平处理请求策略,默认true
                .fairCallHandlingStrategyEnabled(true)
                //堆栈跟踪,默认true
                .writableStackTraceEnabled(true)
                .build();
        BulkheadRegistry bulkheadRegistry =
                BulkheadRegistry.of(defaultConfig);
        BulkheadRegistry defaultRegistry = BulkheadRegistry.ofDefaults();
        Bulkhead bulkheadA = bulkheadRegistry.bulkhead("Bulkhead-A");
        bulkhead = Bulkhead.of("Bulkhead-B", defaultConfig);
        bulkhead.getEventPublisher()
                .onEvent(event -> System.out.println(event.getEventType().name() + " require!"));
    }

    @GetMapping("/test")
    public String testBulkhead() {
        Supplier<String> decoratedSupplier = Bulkhead
                .decorateSupplier(bulkhead, () -> iTestService.testBulkhead("bulkhead"));
        String result = Try.ofSupplier(decoratedSupplier)
                .recover(throwable -> "Hello from Recovery").get();
        return result;
    }

    private ThreadPoolBulkhead threadPoolBulkhead;
    @PostConstruct
    private void initThreadPoolBulkhead() {
        ThreadPoolBulkheadConfig config = ThreadPoolBulkheadConfig.custom()
                //最大线程数， 默认值处理器个数
                .maxThreadPoolSize(2)
                //核心线程数，默认值处理器个数-1
                .coreThreadPoolSize(1)
                //队列长度，默认100
                .queueCapacity(5)
                //线程空闲等待时间，默认20毫秒
                .keepAliveDuration(Duration.ofSeconds(1))
                .build();
        threadPoolBulkhead = ThreadPoolBulkhead.of("ThreadPoolBulkhead-A", config);
        threadPoolBulkhead.getEventPublisher().onEvent(event -> System.out.println(event.getEventType().name() + " require!"));
    }

    @GetMapping("/test1")
    public String testThreadPoolBulkhead() throws ExecutionException, InterruptedException {
        CompletionStage<String> threadPoolBulkhead = this.threadPoolBulkhead.executeCallable(() -> iTestService.testBulkhead("ThreadPoolBulkhead"));
        return threadPoolBulkhead.toCompletableFuture().get();
    }

}
